home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
ansi
/
hercules.zip
/
GCHAR.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-09-04
|
14KB
|
530 lines
;********************************************************************
;*
;* GRAPHIC CHARACTER HANDLING
;*
;* Dave Tutelman - 8/86
;*
;*-------------------------------------------------------------------
;*
;* Fn 6 Scroll up - not yet implemented
;* Fn 7 Scroll down - not yet implemented
;* Fn 9 Write character with attribute
;* Fn 10 Write character normal
;* Fn 14 Write character Teletypewriter style
;*
;* Also includes subroutines to:
;* get_address convert page/row/col to display address
;* do_char write a character to an address on display
;* do_attrib change a display address to some attribute
;* full_screen_scroll used by Fn 14, when it needs to scroll
;* flash momentarily flash to reverse video and back
;*
;********************************************************************
;
INCLUDE hercbios.h
;-----------------------------------------------
extrn exit_herc_bios:near
public writechar,scroll_up,scroll_down,tty
public scr_start,scr_length,num_rows
;------------------------------------
cseg segment public
assume cs:cseg,ds:bios_data
;
;**************************************************************
;*
;* FUNCTION 6 & 7 - SCROLL UP & DOWN
;* (Placeholder only - not yet implemented)
;*
;* AL = Number of rows to scroll (if 0, blank scroll area)
;* BH = Fill attribute (we ignore, since writechar destroys old attrib)
;* CX = Upper left corner (CH=row, CL=col)
;* DX = Lower right corner (DH=row, DL=col)
;*
;****************************************************************
;
scroll_up:
scroll_down:
;
jmp exit_herc_bios
page
;********************************************************************
;*
;* FUNCTION 9 & 10 - WRITE A CHARACTER AT CURRENT CURSOR
;*
;* AL = character code to be written
;* AH = 9 (write char with attribute) or 10 (write char normal)
;* BL = new attribute (limited selection in graphics mode)
;* BH = display page number
;* CX = count of how many characters to write
;*
;********************************************************************
;
writechar:
; ; Get the address corresponding to cursor[page]
push bx
mov bl,bh ; page to BX
xor bh,bh
shl bx,1 ; *2 for word pointer
mov dx,curs_pos[bx] ; appropriate cursor position to DX
pop bx
call get_address ; get display address in DI
;
wrchar_loop:
; ; Write a character to that address
call do_char ; arguments set up already
;
; ; If function 9, modify the character's attributes
cmp ah,9 ; Function 9?
jne no_attrib ; no, don't do attributes
call do_attrib ; yes, and arguments already set up
no_attrib:
;
inc di ; move to next position, without moving
; the official cursor
loop wrchar_loop ; continue until CX count exhausted
jmp exit_herc_bios
page
;*****************************************************************
;*
;* FUNCTION 14 - TELETYPEWRITER-STYLE CHARACTER WRITE
;*
;* AL = Character to be written
;*
;******************************************************************
;
tty:
assume ds:bios_data
mov bl,active_page ; active page to BX
xor bh,bh
mov dx,curs_pos[bx] ; get cursor for active page
push bx
mov bh,bl ; move page to BH
call get_address ; address of character to DI
pop bx
;
; ; process the character
; ; check if CR
cmp al,13 ; carriage return?
jne not_cr
mov dl,0 ; go to first column
jmp fix_curs
; ; check if LF
not_cr: cmp al,10 ; line feed?
jne not_lf
inc dh ; next line
jmp fix_curs
; ; check if BS
not_lf: cmp al,8 ; backspace?
jne not_bs
cmp dl,0 ; already first column?
je fix_curs ; yup. do nothing
dec dl ; nope. move cursor left one
dec di ; also move address pointer left one
mov al,32 ; set character to space
call do_char ; and write the space, but don't move
jmp fix_curs
; ; check if BEL
not_bs: cmp al,7 ; bell character?
jne not_bl
pop es ; restore registers
pop di
pop si
pop dx
pop cx
pop bx
pop ds
jmp vid_bios ; ... and use the normal BIOS to ring the bell
; call flash ; can't do BEL standard. Blink display instead
; jmp fix_curs
; ; ordinary printing character, so display it
not_bl: call do_char ; write it to screen
inc dl ; cursor one to the right
;
; ; now look at the cursor, do what's necessary to
; ; fix it up, and save it away.
fix_curs:
cmp dl,89 ; beyond last column?
jle chk_scroll ; not yet
xor dl,dl ; yes. do a CR
inc dh ; ... and a LF
chk_scroll:
cmp dh,cs:num_rows ; now see if we're beyond last row?
jl exit_tty ; not yet
call full_screen_scroll
; yes. Scroll the screen up one
dec dh ; ... and scroll cursor, too.
jmp chk_scroll
;
exit_tty:
mov curs_pos[bx],dx ; save cursor position
jmp exit_herc_bios
page
;--------------------------------------------------------------------
;
; GET_ADDRESS SUBROUTINE
;
; BH = display page
; DX = cursor position (DH=row, DL=col)
;
; returns:
; DI = displacement of top row of pixels
;
;--------------------------------------------------------------------
;
get_address:
push cx ; save it
; ; compute display address from cursor_pos
mov cl,dh ; get row # in cx
xor ch,ch
shl cx,1 ; begin fast multiply by 90 (1011010 B)
mov di,cx
shl cx,1
shl cx,1
add di,cx
shl cx,1
add di,cx
shl cx,1
shl cx,1
add di,cx ; end fast multiply by 90
mov cx,di ; copy answer back to cx
shl di,1 ; *2 for ibm graphics mode
cmp video_mode,herc_mode
jne ibm_ad ; not herc mode
add di,cx ; *3 for herc mode
ibm_ad: xor ch,ch ; columns in CX
mov cl,dl
add di,cx ; add in col. address in DI
cmp bh,0 ; if page 1, set high-order bit of address
je pg0
or di,8000H
pg0:
; ; address now in DI
;
pop cx ; restore it
ret
page
;--------------------------------------------------------------------
;
; DO_CHAR SUBROUTINE
;
; AL = character to write
; DI = diplacement (address) of top row of pixels
;
; Note: SI and ES are destroyed
;
;--------------------------------------------------------------------
;
do_char:
push ax
push bx
push cx
push di
push ds
;
; ; get scan pattern table pointer into BX
cmp video_mode,herc_mode
je herc_1
mov bx,offset ibm_pattern
; IBM graphics mode - use appropriate table
jmp c_1
herc_1: mov bx,offset herc_pattern
; herc graphics mode - use appropriate table
c_1:
;
; ; set up source address registers
xor ah,ah ; character to SI
mov si,ax
IFDEF iAPX286
shl si,3 ; *8 for 8-byte table entry
ELSE
shl si,1 ; *8 for 8-byte table entry
shl si,1
shl si,1
ENDIF
; next, find beginning of table
cmp al,7Fh ; ROM or user table?
jg u_tbl
; ROM table
add si,charbase ; character table base added to offset
mov ax,mpx_bios ; BIOS code segment to DS
mov ds,ax
jmp c_2
u_tbl: ; user table
xor ax,ax ; zero (interrupt vector) to DS
mov ds,ax
mov ax,si ; save table offset in AX
assume ds:intvec
lds si,user_table ; load DS:SI from interrupt vector
add si,ax ; add offset into table base
c_2:
;
; ; set up destination address registers
mov ax,pixbase ; get display segment in ES
mov es,ax
; displacement already in DI
;
;
; ; transfer the character
mov ax,di ; save top-row displacement in AX
mov cx,8 ; transfer 8 rows
cld ; direction = up
c_loop: mov di,ax ; top-row displacement
add di,cs:[bx] ; add entry from scan-pattern table
movsb ; actually transfer a byte and bump SI & DI
add bx,2 ; next entry in scan-pattern table
loop c_loop
;
; ; if hercules mode, blank the extra rows
pop ds ; restore DS to Bios data
assume ds:bios_data
cmp video_mode,herc_mode
jne c_3
; Hercules mode
mov si,ax ; don't need SI. Save top-row displacement
xor ax,ax ; zero AX
mov cx,4 ; four rows to blank
cld
c_blnk: mov di,si ; top-row displacement
add di,cs:[bx] ; add entry from scan-pattern table
stosb ; transfer a zero byte
add bx,2 ; next entry in scan-pattern table
loop c_blnk
c_3:
;
; ; clean up and return
pop di
pop cx
pop bx
pop ax
ret
page
;------------------------------------------------------------------